package com.cloudkinto.service.platform.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.utils.AmazonUtil;
import com.cloudkinto.common.utils.XmlUtils;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.PlatformStoreDao;
import com.cloudkinto.entity.PlatformStoreDo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RequiredArgsConstructor

public abstract class AmazonBaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {
    protected Logger log = LoggerFactory.getLogger(AmazonBaseServiceImpl.class);
    @Autowired
    protected  RedisTemplate redisTemplate;
    protected String AMZACCESSTOKEN = "AMZACCESSTOKEN:";
    protected String AMZRDTTOKEN = "AMZDRTTOKEN:";
    protected String AMZADACCESSTOKEN = "AMZADACCESSTOKEN:";
    protected String STSSESSIONTOKEN = "STSSESSIONSTOKEN";
    @Autowired
    private PlatformStoreDao platformStoreDao;

    protected String getAmzSpClientSecret() {
        return GlobalConstants.AmzSpClientSecret;
    }


    protected String getAccessToken(PlatformStoreDo shopDo) {
        String accessToken = (String) redisTemplate.opsForValue().get(AMZACCESSTOKEN + shopDo.getId());
        if (accessToken != null) {
            return accessToken;
        }
        String sessionTokenData = getAwsSTSSessionToken(shopDo.getRegionCode());
        JSONObject result = null;
        try {
            result = AmazonUtil.spGetToken(GlobalConstants.AmzSpClientId, getAmzSpClientSecret(), shopDo.getAppSecret(), sessionTokenData, StaticDict.PlatformOrder_Amazon_Market.getRegionName(shopDo.getRegionCode()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (result == null) {
            return null;
        }
        accessToken = result.getString("access_token");
        String refresh_token = result.getString("refresh_token");
        if (StringUtils.isNotBlank(accessToken)) {
            redisTemplate.opsForValue().set(AMZACCESSTOKEN + shopDo.getId(), accessToken, 3000, TimeUnit.SECONDS);
            return accessToken;
        } else if (StringUtils.isNotBlank(result.getString("error_description"))) {
            //没获取到 去更新授权状态 过期了
            Map<String, Object> param = new HashMap<>();
            param.put("shopId", shopDo.getId());
            param.put("type", "sp");
            log.error("店铺：" + shopDo.getId() + " 获取accessToken失败。" + result.getString("error_description"));
            if (result.getString("error_description").contains("The request has an invalid grant parameter : refresh_token. User may have revoked or didn't grant the permission")) {
                //todo 去更新授权状态 过期了
//                rabbitTemplate.convertAndSend("amazon.updateAuthStatus", JSON.toJSONString(param));
            }
        }
        return null;
    }


    protected String getAccessToken(Long shopId) throws Exception {
        PlatformStoreDo shopDo = platformStoreDao.selectById(shopId);
        return getAccessToken(shopDo);
    }



    protected String getRDTAccessToken(PlatformStoreDo shopDo) {
        String rdtToken = (String) redisTemplate.opsForValue().get(AMZRDTTOKEN + shopDo.getId());
        if (rdtToken != null) {
            return rdtToken;
        }
        List<String> element = new ArrayList<>();
        String path = "/orders/v0/orders";
        element.add("buyerInfo");
        element.add("shippingAddress");
//        if (type == 0) {
//            element.add("shippingAddress");
//            if (StringUtils.isEmpty(amazonOrderId))
//                path = "/orders/v0/orders";
//            else
//                path = "/orders/v0/orders/" + amazonOrderId;
//        } else {
//            path = "/orders/v0/orders/" + amazonOrderId + "/orderItems";
//        }
        String sessionTokenData = getAwsSTSSessionToken(shopDo.getRegionCode());
        String accessToken = null;
        try {
            accessToken = getAccessToken(shopDo);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            rdtToken = AmazonUtil.spGetRdtToken(StaticDict.PlatformOrder_Amazon_Market.getEndpoint(shopDo.getRegionCode()), "GET", path
                    , element, accessToken, sessionTokenData, StaticDict.PlatformOrder_Amazon_Market.getRegionName(shopDo.getRegionCode()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (rdtToken == null) {
            return null;
        }
        redisTemplate.opsForValue().set(AMZRDTTOKEN + shopDo.getId(), rdtToken, 3000, TimeUnit.SECONDS);
        return rdtToken;
    }

    protected String getAwsSTSSessionToken(String regionCode) {
        JSONObject jsonObject;
        jsonObject = (JSONObject) redisTemplate.opsForValue().get(STSSESSIONTOKEN);
        if (jsonObject != null) {
            GlobalConstants.accessSecrityKeySP = jsonObject.getString("AccessKeyId");
            GlobalConstants.secretSecrityKeySP = jsonObject.getString("SecretAccessKey");
            return jsonObject.getString("SessionToken");
        }
        Map<String, Object> parametersMap = new HashMap<>();
        parametersMap.put("Action", "AssumeRole");
        parametersMap.put("Version", "2011-06-15");
        parametersMap.put("RoleArn", "arn:aws:iam::975458911230:role/FBA-SP-API");
        parametersMap.put("RoleSessionName", "dingSession");
        String body = null;
        try {
            if (StaticDict.PlatformOrder_Amazon_Market.NA.getValue().equals(regionCode)) {
                body = AmazonUtil.awsSTS("https://sts.us-east-1.amazonaws.com/", "us-east-1", parametersMap);
            } else if (StaticDict.PlatformOrder_Amazon_Market.EU.getValue().equals(regionCode)) {
                body = AmazonUtil.awsSTS("https://sts.eu-west-1.amazonaws.com/", "eu-west-1", parametersMap);
            } else if (StaticDict.PlatformOrder_Amazon_Market.FE.getValue().equals(regionCode)) {
                body = AmazonUtil.awsSTS("https://sts.us-west-2.amazonaws.com/", "us-west-2", parametersMap);
            }
            jsonObject = XmlUtils.xml2Json(body);
            if (jsonObject == null) {
                return null;
            }
            JSONObject resultData = jsonObject.getJSONObject("AssumeRoleResponse").getJSONArray("AssumeRoleResult").getJSONObject(0).getJSONArray("Credentials").getJSONObject(0);
            redisTemplate.opsForValue().set(STSSESSIONTOKEN, resultData, 3000, TimeUnit.SECONDS);
            GlobalConstants.accessSecrityKeySP = resultData.getString("AccessKeyId");
            GlobalConstants.secretSecrityKeySP = resultData.getString("SecretAccessKey");
            return resultData.getString("SessionToken");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
